home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 August: Tool Chest / Dev.CD Aug 00 TC Disk 2.toast / pc / sample code / quicktime / codecs / drawtextcodec / codectestmain.c next >
Encoding:
C/C++ Source or Header  |  2000-06-23  |  26.2 KB  |  1,183 lines

  1. /*
  2.     File:        CodecTestMain.c
  3.  
  4.     Contains:    
  5.  
  6.     Written by: Mark Krueger    
  7.  
  8.     Copyright:    Copyright © 1992-1999 by Apple Computer, Inc., All Rights Reserved.
  9.  
  10.                 You may incorporate this Apple sample source code into your program(s) without
  11.                 restriction. This Apple sample source code has been provided "AS IS" and the
  12.                 responsibility for its operation is yours. You are not permitted to redistribute
  13.                 this Apple sample source code as "Apple sample source code" after having made
  14.                 changes. If you're going to re-distribute the source, we require that you make
  15.                 it clear in the source that the code was descended from Apple sample source
  16.                 code, but that you've made changes.
  17.  
  18.     Change History (most recent first):
  19.                 7/29/1999    Karl Groethe    Updated for Metrowerks Codewarror Pro 2.1
  20.                 
  21.  
  22. */
  23.  
  24.  
  25. #ifdef    THINK_C
  26. //#define    OpenStdCompression    OPENSTDCOMPRESSION
  27. #endif
  28.  
  29.  
  30. #include    <QuickTimeComponents.h>
  31. #include    <ImageCompression.h>
  32. #include    "DrawTextCodec.h"
  33.  
  34. #define    dangerousPattern
  35.  
  36. //#define    DONT_SHOW_PICTURE
  37. //#define    DONT_DO_PREVIEW
  38.  
  39. #include    <Types.h>
  40. #include    <Files.h>
  41. #include    <Quickdraw.h>
  42. #include    <Packages.h>
  43. #include    <Memory.h>
  44. #include    <Fonts.h>
  45. #include    <Events.h>
  46. #include    <OSUtils.h>
  47. #include    <ToolUtils.h>
  48. #include    <Menus.h>
  49. #include    <Dialogs.h>
  50. #include    <stdio.h>
  51. #include    <Errors.h>
  52. #include    <Scrap.h>
  53. #include    <Desk.h>
  54. #include    <string.h>
  55. #include    <GestaltEqu.h>
  56. #include    <Resources.h>
  57. #include    <Finder.h>
  58. #include    <palettes.h>
  59. #include    <PictUtils.h>
  60. #include    <QDOffscreen.h>
  61. #include    <Windows.h>
  62. #include    <FixMath.h>
  63. #include    <ImageCodec.h>
  64.  
  65. #ifndef    THINK_C
  66. #include    <Strings.h>
  67. #endif
  68.  
  69.  
  70. #include    <ImageCompression.h>
  71.  
  72.  
  73.  
  74. #define        appleMenuID        128
  75. #define        fileMenuID        129
  76. #define        editMenuID        130
  77.  
  78.  
  79. #define        M_OPEN            1
  80. #define        M_CLOSE            3
  81. #define        M_SAVE            4
  82. #define        M_COMP            6
  83. #define        M_QUIT            8
  84.  
  85. #define        M_COPY            4
  86. #define        M_PASTE            5
  87. #define        M_FIT            10
  88.  
  89.  
  90. Boolean        gDitherFlag  = false;
  91. StandardFileReply    gOriginalSFR;    
  92. short            gOriginalFile;
  93. Cursor            **gWatch;
  94. short            gCompressedFile;
  95. Boolean            gExitFlag = false;
  96. MenuHandle        gMenus[3];            // our menus
  97. CWindowPtr        gActiveWindow = nil;
  98. CWindowPtr        gOrigWindow = nil;
  99. CWindowPtr        gCompWindow = nil;
  100. Rect            gOriginalPicFrame;
  101. Rect            gZoomedPictureFrame;
  102. Boolean            gZoomed = false;
  103. Boolean            gFitToWindow = true;
  104. Boolean            gHasNewStdFile = false;
  105. PicHandle        gOriginalPicture = nil;
  106. Boolean            gCompressed = false;
  107. Boolean            gSevenOh = false;
  108. short            gDepth = 1;
  109.  
  110.  
  111. ComponentInstance    gSCComponent;
  112. SCParams            gSCParams;
  113.  
  114. Boolean            gDidError = false;
  115.  
  116. GWorldPtr    gworld,compgworld;
  117. int Initialize();
  118. void Error(char *msg);
  119. pascal OSErr
  120. Progress(short progressMsg,Fixed progressPercent,long refcon);
  121. int DoCompression(CWindowPtr    window);
  122. void DoError();
  123. void FitRect(Rect *rect,short w,short h);
  124. void DoOpen(FSSpec *fsp);
  125. void DoClose(CWindowPtr w);
  126. void DoSave(CWindowPtr w) ;
  127. void FixMenus();
  128. void DoPaste();
  129. void DoCopy(CWindowPtr w);
  130. void DoUpdate(CWindowPtr w);
  131. void DoSizeWindow(CWindowPtr wind,short h,short v,Boolean fup);
  132. void DoZoom(WindowPtr wind);
  133. void DoGrow(WindowPtr wind,Point *where);
  134. void DoCommand(long    mResult);
  135.  
  136. /************************************************
  137.  *
  138.  *    Set up application environment.
  139.  *
  140.  ************************************************/
  141.  
  142.  
  143. int Initialize()
  144. {
  145.     Ptr    size;
  146.     
  147.     size = GetApplLimit();
  148.     SetApplLimit(size - 32*1024);        /* make room on stack so Quickdraw can do big pictures */
  149.     MaxApplZone();
  150.  
  151.     /*    initialize managers */
  152.  
  153.     InitGraf(&qd.thePort);
  154.     InitFonts();
  155.     InitWindows();
  156.     InitMenus();
  157.     InitDialogs(nil);
  158.     InitCursor();
  159.     ErrorSound(nil);
  160.     
  161.     /*    install menus */
  162.     
  163.     if ( (gMenus[0] = GetMenu(appleMenuID)) == nil )
  164.         return(-1);
  165.     AppendResMenu(gMenus[0], (ResType) 'DRVR');
  166.     InsertMenu(gMenus[0], 0);
  167.     if ( (gMenus[1] = GetMenu(fileMenuID)) == nil )
  168.         return(-1);
  169.     InsertMenu(gMenus[1], 0);
  170.     if ( (gMenus[2] = GetMenu(editMenuID)) == nil )
  171.         return(-1);
  172.     InsertMenu(gMenus[2], 0);
  173.     DrawMenuBar();
  174.     if ( (gWatch =  GetCursor(watchCursor)) == nil )
  175.         return(-1);
  176.     HNoPurge((Handle)gWatch);
  177.     return(0);
  178. }
  179.  
  180.  
  181. /************************************************
  182.  *
  183.  *    Report errors as needed.
  184.  *
  185.  ************************************************/
  186.  
  187. void Error(char *msg)
  188. {
  189.     SysBeep(1);
  190.     ParamText("\pError:",c2pstr(msg),nil,nil);    /* oops da baby */
  191.     Alert(128,nil);
  192. }
  193.  
  194.  
  195. /************************************************
  196.  *
  197.  *    Progress proc called from the Image Compression manager.
  198.  *
  199.  ************************************************/
  200.  
  201.  
  202. pascal OSErr
  203. Progress(short progressMsg,Fixed progressPercent,long refcon)
  204. {
  205.     OSErr  result = noErr;
  206.     short kind;
  207.     Handle h;
  208.     Rect r;
  209.     CGrafPtr savePort,wmgPort;
  210.     GDHandle saveGD;
  211.     static DialogPtr progressDialog = 0;
  212.     KeyMap    keys;
  213.  
  214.     switch (progressMsg) {
  215.     
  216.     case codecProgressOpen:
  217.     
  218.         progressDialog = 0;
  219.         GetGWorld(&savePort,&saveGD);
  220.         GetCWMgrPort(&wmgPort);
  221.         SetGWorld(wmgPort,nil);
  222.         if ( refcon != -1 && (progressDialog = GetNewDialog(5002, 0, (WindowPtr)-1)) != nil ) { 
  223.             ShowWindow((WindowPtr)progressDialog);
  224.             SetGWorld((CGrafPtr)progressDialog,nil);
  225.             DrawDialog(progressDialog);
  226.             GetDialogItem(progressDialog, 1, &kind, &h, &r);
  227.             InsetRect(&r, -1, -1);
  228.             FrameRect(&r);
  229.             InsetRect(&r, 1, 1);
  230.         }
  231.         SetGWorld(savePort,saveGD);
  232.         break;
  233.  
  234.     case codecProgressUpdatePercent:
  235.     
  236.         if ( progressDialog ) {
  237.             GetGWorld(&savePort,&saveGD);
  238.             SetGWorld((CGrafPtr)progressDialog,nil);
  239.             GetDialogItem(progressDialog, 1, &kind, &h, &r);
  240.             
  241.             FillRect(&r,&qd.gray);
  242.             r.right = r.left + FixRound( FixMul(progressPercent, FixRatio(r.right-r.left,1)));
  243.             PaintRect(&r);
  244.             SetGWorld(savePort,saveGD);
  245.         }    
  246.  
  247.         /* check for command period - not the best way, but it works */
  248.  
  249.         GetKeys(keys);
  250.         if ( (keys[1] & 0x8000) && ((0x800000 & keys[1]) || (0x2000000 & keys[1])  ) )
  251.             result = codecAbortErr;
  252.         break;
  253.     
  254.     case codecProgressClose:
  255.     
  256.         if ( progressDialog )
  257.             DisposeDialog(progressDialog);
  258.         progressDialog = 0;
  259.         break;
  260.     }
  261.     return(result);
  262. }
  263.  
  264.     
  265. /************************************************
  266.  *
  267.  *    Allow the user to specify compression and an output file, and then
  268.  *  compress the picture and save the result in that file.
  269.  *
  270.  ************************************************/
  271.  
  272.  
  273. int DoCompression(CWindowPtr    window)
  274. {
  275.  
  276.     /* StdFile stuff */
  277.     
  278.     CGrafPtr    savePort;
  279.     GDHandle    saveGD;
  280.  
  281.     /* for sepecifying compression */
  282.     
  283.     Rect        pictureFrame;
  284.     OSErr        result;
  285.     Point        where;
  286.     ImageDescriptionHandle desc = nil;
  287.     Ptr    data = nil;
  288.     long    cdsize;
  289.     ICMProgressProcRecord    *progP,progressRec;
  290.     Str255        buf;
  291.     GrafPtr        wmPort;
  292.     
  293.     progressRec.progressProc = NewICMProgressProc(Progress);
  294.     progressRec.progressRefCon = 0;
  295.     progP = &progressRec;
  296.         
  297.  
  298.     if ( window == nil )
  299.         return -1;
  300.     pictureFrame = ((CGrafPtr)window)->portRect;
  301.  
  302.     /************************************************
  303.      *
  304.      *        Ask how the user wants to compress it.
  305.      *
  306.      ************************************************/
  307.  
  308.  
  309.     
  310.     SetCursor(&qd.arrow);
  311.     if (SCSetTestImagePixMap(gSCComponent,gworld->portPixMap,&gworld->portRect,0))
  312.         goto done;
  313.  
  314.  
  315.     GetWMgrPort(&wmPort);
  316.     SetPort(wmPort);
  317.     where.h = where.v = -2;        // position dialog on the best device
  318.     if (SCGetCompression(gSCComponent,&gSCParams,where))
  319.         goto done;
  320.     
  321.     /************************************************
  322.      *
  323.      *        Ask her for the name of the new file.
  324.      *
  325.      ************************************************/
  326.     
  327.  
  328.     SetCursor(*gWatch);
  329.  
  330.  
  331.     if ( (result=GetMaxCompressionSize(gworld->portPixMap,&gworld->portRect,
  332.             gSCParams.depth,gSCParams.spatialQuality,gSCParams.theCodecType,
  333.             gSCParams.theCodec,&cdsize)) != noErr ) {
  334.         Error("getting max comp size");
  335.         goto done;
  336.     }        
  337.     if ( (data=NewPtr(cdsize)) == nil ) {
  338.         Error("no mem for picture");
  339.         goto done;
  340.     }        
  341.     desc = (ImageDescriptionHandle)NewHandle(sizeof(ImageDescription));
  342.     if ( desc == nil ) {
  343.         DisposePtr(data);
  344.         Error("no mem for picture");
  345.         goto done;
  346.     }        
  347.         
  348.     if ( (result=FCompressImage(gworld->portPixMap,&gworld->portRect,
  349.                 gSCParams.depth,gSCParams.spatialQuality,gSCParams.theCodecType,
  350.                 gSCParams.theCodec,nil,0,0,nil,progP,
  351.                  desc,data)) != noErr   ) {
  352.          DisposePtr(data);
  353.          DisposeHandle((Handle)desc);
  354.          if ( result != codecAbortErr ) 
  355.             Error("compressing picture");
  356.         goto done;
  357.     }    
  358.     
  359.     
  360.     NumToString((*desc)->dataSize,buf);
  361.     ParamText("\pCompressed to ",buf,"\pBytes",nil);
  362.     Alert(128,nil);
  363.     GetGWorld(&savePort,&saveGD);
  364.     SetGWorld(compgworld,nil);
  365.     
  366.     if ( (result=DecompressImage(data,desc,compgworld->portPixMap,
  367.                     &gworld->portRect,&compgworld->portRect,ditherCopy,nil)) != noErr ) {
  368.          DisposePtr(data);
  369.          DisposeHandle((Handle)desc);
  370.         Error("compressing picture");
  371.         goto done;
  372.     }    
  373.      DisposePtr(data);
  374.      DisposeHandle((Handle)desc);
  375.      SetGWorld(gCompWindow,nil);
  376.      InvalRect(&gCompWindow->portRect);
  377.     SetGWorld(savePort,saveGD);
  378. done:
  379.     gDidError = false;
  380.     SetCursor(&qd.arrow);
  381.     
  382.     return(result);
  383. }
  384.  
  385.     
  386.     
  387.     
  388.  
  389.  
  390. void DoError()
  391. {
  392.     CGrafPtr    savePort;
  393.     GDHandle    saveGD;
  394.     RGBColor    opColor;
  395.     
  396.     
  397.     GetGWorld(&savePort,&saveGD);
  398.     SetGWorld(compgworld,nil);
  399.     if ( !gDidError ) {
  400.         gDidError = true;
  401.         opColor.red = opColor.green = opColor.blue = 0;
  402.         OpColor(&opColor);
  403.         CopyBits((BitMap *)*gworld->portPixMap,(BitMap *)*((CGrafPtr)compgworld)->portPixMap,
  404.             &gworld->portRect,&compgworld->portRect,subPin,nil);
  405.     }
  406.     opColor.red = opColor.green = opColor.blue = 0xffff;
  407.     OpColor(&opColor);
  408.     CopyBits((BitMap *)*compgworld->portPixMap,(BitMap *)*((CGrafPtr)compgworld)->portPixMap,
  409.         &compgworld->portRect,&compgworld->portRect,addPin,nil);
  410.      SetGWorld(gCompWindow,nil);
  411.      InvalRect(&gCompWindow->portRect);
  412.     SetGWorld(savePort,saveGD);
  413. }
  414.  
  415.  
  416.     
  417. /************************************************
  418.  *
  419.  *    Massage a rectangle to fit on a device's screen.
  420.  *
  421.  ************************************************/
  422.  
  423.  
  424. void FitRect(Rect *rect,short w,short h)
  425. {
  426.     short     n;
  427.     Rect    dRect;
  428.     GDHandle    gd;
  429.     
  430. //    dRect = *rect;
  431.     gd = GetGDevice();
  432.     dRect =(*gd)->gdRect;
  433.     dRect.top += 40;                                /* make way for title bar */
  434.     InsetRect(&dRect,16,16);
  435.  
  436.     if ( w < (dRect.right-dRect.left) &&  h < (dRect.bottom-dRect.top) ) {
  437.          dRect.right = dRect.left + w;
  438.          dRect.bottom = dRect.top + h;
  439.     } else if ( gFitToWindow ) {
  440.         n = dRect.top + ((dRect.right -dRect.left) * h)/w;
  441.         if ( n > dRect.bottom )
  442.             dRect.right = dRect.left +((dRect.bottom -dRect.top) * w)/h;
  443.         else 
  444.             dRect.bottom = n;
  445.     }
  446.     *rect = dRect;
  447.  
  448. }
  449.  
  450.  
  451.     
  452. /************************************************
  453.  *
  454.  *    Ask the user for a pict file to open and open it.
  455.  *
  456.  ************************************************/
  457.  
  458.  
  459. void DoOpen(FSSpec *fsp)
  460. {
  461.     OpenCPicParams    originalPicHeader;
  462.     SFTypeList     types = { 'PICT',0 };
  463.     OSErr        result = noErr;
  464.     long        size;
  465.     CGrafPtr    savePort;
  466.     GDHandle    saveGD;
  467.     Rect        rect;
  468.     
  469.     
  470.     if ( fsp == nil ) {
  471.         if ( gHasNewStdFile )
  472.             StandardGetFile(nil,1,types,&gOriginalSFR);
  473.         else {
  474.             SFReply        osfr;
  475.             Point    pt = {100,100};
  476.             
  477.             SFGetFile(pt,(ConstStr255Param)"",nil,1,types,nil,&osfr);
  478.             gOriginalSFR.sfGood = osfr.good;
  479.             gOriginalSFR.sfReplacing = osfr.copy;
  480.             gOriginalSFR.sfType = osfr.fType;
  481.             if ( osfr.good ) 
  482.                 FSMakeFSSpec(osfr.vRefNum,0L,osfr.fName,&gOriginalSFR.sfFile);
  483.         }
  484.         if ( !gOriginalSFR.sfGood  ) {
  485.             return ;
  486.         }
  487.     } else {
  488.         gOriginalSFR.sfFile = *fsp;
  489.     }
  490.         
  491.     SetCursor(*gWatch);
  492.     if ((result=FSpOpenDF(&gOriginalSFR.sfFile,fsRdPerm,&gOriginalFile)) != noErr ) {
  493.         goto done;
  494.     }
  495.  
  496.     
  497.     
  498.     /************************************************
  499.      *
  500.      *    Get the picture frame, to see how big of a window to make.
  501.      *
  502.      ************************************************/
  503.  
  504.     if ( (result=GetPictureFileHeader(gOriginalFile,&gOriginalPicFrame,&originalPicHeader)) != noErr ) {
  505.         FSClose(gOriginalFile);
  506.         goto done;
  507.     }
  508.  
  509.  
  510.     /************************************************
  511.      *
  512.      *    Figure out the best screen to show the picture on, and if
  513.      *    it doesn't fit, then scale it to fit while maintaining aspect ratio.
  514.      *
  515.      ************************************************/
  516.     
  517.     
  518.     SetRect(&gZoomedPictureFrame,-32767,-32767,32767,32767);
  519.     FitRect(&gZoomedPictureFrame,gOriginalPicFrame.right-gOriginalPicFrame.left,
  520.         gOriginalPicFrame.bottom-gOriginalPicFrame.top);
  521.     gZoomed = false;
  522.  
  523.     /************************************************
  524.      *
  525.      *    Create a window for the picture, and set our port to it.
  526.      *
  527.      ************************************************/
  528.  
  529.     if ( (gOrigWindow = (CWindowPtr)NewCWindow(nil,&gZoomedPictureFrame,gOriginalSFR.sfFile.name,true,
  530.                 zoomDocProc,(WindowPtr)-1,true,0)) == nil ) {
  531.         FSClose(gOriginalFile);
  532.         result = -1;
  533.         goto done;
  534.     }
  535.     rect = gZoomedPictureFrame;
  536. //    OffsetRect(&rect,(rect.right-rect.left)+10,0);
  537.     OffsetRect(&rect,50,50);
  538.     if ( (gCompWindow = (CWindowPtr)NewCWindow(nil,&rect,"\pCompressed",true,
  539.                 zoomDocProc,(WindowPtr)-1,true,0)) == nil ) {
  540.         FSClose(gOriginalFile);
  541.         result = -1;
  542.         goto done;
  543.     }
  544.     SetPort((GrafPtr)gActiveWindow);
  545.     if ( GetEOF(gOriginalFile,&size) == noErr ) {
  546.         size -= 512;
  547.         if ( gOriginalPicture = (PicHandle)NewHandle(size) ) {
  548.             HLock((Handle)gOriginalPicture);
  549.             SetFPos(gOriginalFile,fsFromStart,512);
  550.             FSRead(gOriginalFile,&size,*(Handle)gOriginalPicture);
  551.             HUnlock((Handle)gOriginalPicture);
  552.             HPurge((Handle)gOriginalPicture);
  553.         }
  554.     }    
  555.     rect = gZoomedPictureFrame;    
  556.     OffsetRect(&rect,-rect.left,-rect.top);
  557.     
  558.     if ( (result=NewGWorld(&gworld,gDepth,&rect,nil,nil,0)) != 0 ) {
  559.         if ( (result=NewGWorld(&gworld,gDepth,&rect,nil,nil,8)) != 0 ) {
  560.             Error("No mem for gworld");
  561.             goto done;
  562.         }
  563.     }
  564.     if ( (result=NewGWorld(&compgworld,gDepth,&rect,nil,nil,0)) != 0 ) {
  565.         if ( (result=NewGWorld(&compgworld,gDepth,&rect,nil,nil,8)) != 0 ) {
  566.             Error("No mem for gworld");
  567.             DisposeGWorld(gworld);
  568.             gworld = nil;
  569.             goto done;
  570.         }
  571.     }
  572.     GetGWorld(&savePort,&saveGD);
  573.     SetGWorld(gworld,nil);
  574.     if ( gOriginalPicture && *gOriginalPicture) {
  575.         HNoPurge((Handle)gOriginalPicture);
  576.         if ( (result=DrawTrimmedPicture(gOriginalPicture,&rect,nil,gDitherFlag,nil)) != noErr  && result != codecAbortErr) {
  577.             SysBeep(1);
  578.         }
  579.         HPurge((Handle)gOriginalPicture);
  580.     }else {
  581.         if ( (result=DrawTrimmedPictureFile(gOriginalFile,&rect,nil,gDitherFlag,nil)) != noErr  && result != codecAbortErr) {
  582.             SysBeep(1);
  583.         }
  584.     }
  585.     
  586.     SetGWorld(compgworld,nil);
  587.     EraseRect(&compgworld->portRect);
  588.     SetGWorld(savePort,saveGD);
  589.     SetWRefCon((WindowPtr)gCompWindow,(long)compgworld);
  590.     SetWRefCon((WindowPtr)gOrigWindow,(long)gworld);
  591.     FSClose(gOriginalFile);
  592.     if ( gOriginalPicture ) {
  593.         DisposeHandle((Handle)gOriginalPicture);
  594.         gOriginalPicture = nil;
  595.     }
  596. done:
  597.     SetCursor(&qd.arrow);
  598.     if ( result ) {
  599.         SysBeep(1);
  600.     }
  601.  
  602. }
  603.  
  604.     
  605. /************************************************
  606.  *
  607.  *    Close the window and the file and get rid of any temporary file we may have.
  608.  *
  609.  ************************************************/
  610.  
  611.  
  612. void DoClose(CWindowPtr w)
  613. {
  614.     GWorldPtr    gw;
  615.     
  616.     if ( w == nil )
  617.         return;
  618.         
  619.     gw = (GWorldPtr)GetWRefCon((WindowPtr)w);
  620.     if ( gw ) {
  621.         DisposeGWorld(gw);
  622.     }
  623.     CloseWindow((WindowPtr)w);
  624.     if  ( w == gActiveWindow ) {
  625.         gActiveWindow = nil;
  626.     }
  627.     if ( w == gOrigWindow )    
  628.         gOrigWindow = nil;
  629.     if ( w == gCompWindow )    
  630.         gCompWindow = nil;
  631.     return;
  632. }
  633.  
  634. void DoSave(CWindowPtr w) 
  635. {
  636.  
  637.     long    l,k;
  638.     OSErr    e = 0;
  639.     PicHandle    pict = nil;
  640.     long    i;
  641.     short    f = 0;
  642.     static Str255    name = "\pPICT";
  643.     StandardFileReply     sfr;
  644.     CGrafPtr    savePort;
  645.     GDHandle    saveGD;
  646.     GWorldPtr    gw;
  647.     long zero = 0;
  648.     
  649.         
  650.     gw = (GWorldPtr)GetWRefCon((WindowPtr)w);
  651.     if ( gw == nil )
  652.         return;
  653.     StandardPutFile((ConstStr255Param)"",name,&sfr);
  654.     if ( sfr.sfGood ) { 
  655.         GetGWorld(&savePort,&saveGD);
  656.         SetGWorld(gw,nil);
  657.         pict = OpenPicture(&gw->portRect);
  658.         ClipRect(&gw->portRect);
  659.         CopyBits((BitMap *)*gw->portPixMap,(BitMap *)*((CGrafPtr)gw)->portPixMap,
  660.             &gw->portRect,&gw->portRect,ditherCopy,nil);
  661.         ClosePicture();
  662.         SetGWorld(savePort,saveGD);
  663.         if ( (l=GetHandleSize((Handle)pict)) <= 10 ) {
  664.             DisposeHandle((Handle)pict);
  665.             Error("Making Pict");
  666.             return;
  667.         }
  668.         FSpDelete(&sfr.sfFile);
  669.         if ( (e=FSpCreate(&sfr.sfFile,'ppxi','PICT',0)) != noErr  ) {
  670.             Error("Creating file");
  671.             return;
  672.         }
  673.         if ( (e=FSpOpenDF(&sfr.sfFile,fsRdWrPerm,&f)) != noErr ) {
  674.             Error("Opening file");
  675.             goto bail;
  676.         }
  677.         SetFPos(f,fsFromStart,0);
  678.         k = 4;
  679.         for ( i=0; i < 512/4; i++ ) {
  680.             if ( (e=FSWrite(f,&k,(char *)&zero)) != noErr ) {
  681.                 Error("Writing file");
  682.                 goto bail;
  683.             }
  684.         }
  685.         HLock((Handle)pict);
  686.         if ( (e=FSWrite(f,&l,(Ptr)*pict)) != noErr)  {
  687.             Error("Writing file");
  688.             goto bail;
  689.         }
  690.         SetEOF(f,l+512);
  691.  
  692. bail:    
  693.         if ( pict )    
  694.             DisposeHandle((Handle)pict);
  695.         if ( f ) 
  696.             FSClose(f);
  697.         if ( e )
  698.             FSpDelete(&sfr.sfFile);
  699.         FlushVol(nil,sfr.sfFile.vRefNum);
  700.     }
  701. }
  702.  
  703.  
  704.  
  705.     
  706. /************************************************
  707.  *
  708.  *    Fix the menu hiliting based on conditions.
  709.  *
  710.  ************************************************/
  711.  
  712.  
  713. void FixMenus()
  714. {
  715.     
  716.     if ( gActiveWindow == nil ) {
  717.         EnableItem(gMenus[1],M_OPEN);
  718.         DisableItem(gMenus[1],M_CLOSE);
  719.         DisableItem(gMenus[1],M_SAVE);
  720.         DisableItem(gMenus[2],M_COPY);
  721.     } else  { 
  722.         DisableItem(gMenus[1],M_OPEN);
  723.         EnableItem(gMenus[1],M_CLOSE);
  724.         EnableItem(gMenus[1],M_SAVE);
  725. //        EnableItem(gMenus[2],M_COPY);
  726.     }
  727.     
  728.     if ( gOrigWindow != nil && gCompWindow != nil ) 
  729.         EnableItem(gMenus[1],M_COMP);
  730.     else
  731.         DisableItem(gMenus[1],M_COMP);
  732.     EnableItem(gMenus[2],M_FIT);
  733. //    if ( GetScrap(nil,'PICT',&offset) > 0  ) 
  734. //        EnableItem(gMenus[2],M_PASTE);
  735. //    else
  736.         DisableItem(gMenus[2],M_PASTE);
  737. }
  738.  
  739.     
  740. /************************************************
  741.  *
  742.  *    Paste the PICT from the clip board into a new window, making a temporary
  743.  *  file for it.
  744.  *
  745.  ************************************************/
  746.  
  747.  
  748. void DoPaste()
  749. {
  750. }
  751.  
  752.     
  753. /************************************************
  754.  *
  755.  *    Copy the open PICT onto the clip board.
  756.  *
  757.  ************************************************/
  758.  
  759.  
  760. void DoCopy(CWindowPtr w)
  761. {
  762.     #pragma unused(w)
  763. }
  764.     
  765.  
  766. /************************************************
  767.  *
  768.  *    Update the window from the PICT file.
  769.  *
  770.  ************************************************/
  771.  
  772. void DoUpdate(CWindowPtr w)
  773. {
  774.     CGrafPtr        savePort;
  775.     GDHandle        saveGD;
  776.     Rect        srcRect;
  777.     GWorldPtr    gw;
  778.  
  779.  
  780.     if ( w == nil ) 
  781.         return;
  782.     SetCursor(*gWatch);
  783.     GetGWorld(&savePort,&saveGD);
  784.     SetGWorld((CGrafPtr)w,nil);
  785.     
  786.     gw = (GWorldPtr)GetWRefCon((WindowPtr)w);
  787.     if ( gw  ) { 
  788.         srcRect = gw->portRect;
  789.         BeginUpdate((WindowPtr)w);
  790.         CopyBits((BitMap *)*gw->portPixMap,(BitMap *)*((CGrafPtr)w)->portPixMap,
  791.             &srcRect,&((CGrafPtr)w)->portRect,ditherCopy,nil);
  792.     
  793.         EndUpdate((WindowPtr)w);
  794.     }
  795.     SetGWorld(savePort,saveGD);
  796.     SetCursor(&qd.arrow);
  797.  
  798. }
  799.  
  800.     
  801. /************************************************
  802.  *
  803.  *    Resize the window and remember the old size, and force it to update.
  804.  *
  805.  ************************************************/
  806.  
  807.  
  808. void DoSizeWindow(CWindowPtr wind,short h,short v,Boolean fup)
  809. {
  810.     GrafPtr    savePort;
  811.  
  812.     gZoomed = false;
  813.     GetPort(&savePort);
  814.     SetPort((GrafPtr)wind);
  815.     SizeWindow((WindowPtr)wind,h,v,false);
  816.     gZoomedPictureFrame = ((CGrafPtr)wind)->portRect;
  817.     LocalToGlobal((Point *)&gZoomedPictureFrame.top);
  818.     LocalToGlobal((Point *)&gZoomedPictureFrame.bottom);
  819.     if ( fup )
  820.         InvalRect(&((CWindowPtr)wind)->portRect);
  821.     SetPort(savePort);
  822. }
  823.  
  824.     
  825. /************************************************
  826.  *
  827.  *    Handle clicks in the window zoom box.
  828.  *
  829.  ************************************************/
  830.  
  831. void DoZoom(WindowPtr wind)
  832. {
  833.     Rect         rect;
  834.     Rect         saveRect;
  835.     GrafPtr        savePort;
  836.     KeyMap        keys;
  837.     Boolean        doOriginal;
  838.     
  839.     GetPort(&savePort);
  840.     SetPort((GrafPtr)wind);
  841.  
  842.     GetKeys(keys);
  843.     doOriginal = (( keys[1] & 4 ) != 0);        /* option key */
  844.  
  845.     if ( doOriginal ) {
  846.         gZoomed = false;
  847.         FitRect(&gZoomedPictureFrame,gOriginalPicFrame.right-gOriginalPicFrame.left,
  848.             gOriginalPicFrame.bottom-gOriginalPicFrame.top);
  849.     } else {
  850.         if ( gZoomed ) {
  851.             gZoomed = false;
  852.         } else {
  853.             rect = gZoomedPictureFrame;
  854.             rect.top += 16;                        /* make way for title bar */
  855.             InsetRect(&rect,16,16);
  856.             ShowHide(wind,0);
  857.             MoveWindow(wind,rect.left,rect.top,true);
  858.             saveRect = gZoomedPictureFrame;
  859.             DoSizeWindow((CWindowPtr)wind,rect.right-rect.left,rect.bottom-rect.top,true);
  860.             gZoomedPictureFrame = saveRect;
  861.             gZoomed = true;
  862.             goto done;
  863.         }
  864.     }
  865.     ShowHide(wind,0);
  866.     MoveWindow(wind,gZoomedPictureFrame.left,gZoomedPictureFrame.top,true);
  867.     DoSizeWindow((CWindowPtr)wind,gZoomedPictureFrame.right-gZoomedPictureFrame.left,
  868.         gZoomedPictureFrame.bottom-gZoomedPictureFrame.top,true);
  869. done:
  870.     ShowHide(wind,1);
  871.     SetPort(savePort);
  872. }
  873.  
  874.  
  875.  
  876. /************************************************
  877.  *
  878.  *    Grow the window (constrain aspect ratio if option key pressed.
  879.  *
  880.  ************************************************/
  881.  
  882.  
  883. void DoGrow(WindowPtr wind,Point *where)
  884. {
  885.     unsigned long     size;
  886.     Rect            sizeRect;
  887.     GrafPtr            savePort;
  888.     short            h,v;
  889.     short            height = gOriginalPicFrame.bottom - gOriginalPicFrame.top;
  890.     short            width = gOriginalPicFrame.right - gOriginalPicFrame.left;
  891.     KeyMap            keys;
  892.     short            minH = 128,minV = 128,maxH = 4096,maxV = 4096;
  893.     Boolean            maintainAspect;
  894.     Rect            rect;
  895.     
  896.     
  897.     GetPort(&savePort);
  898.     SetPort((GrafPtr)wind);
  899.     GetKeys(keys);
  900.     maintainAspect = (( keys[1] & 4 ) != 0);
  901.     if ( maintainAspect ) {
  902.         Rect    oRect;
  903.         
  904.         rect = ((CGrafPtr)wind)->portRect;
  905.         LocalToGlobal((Point *)&rect.top);
  906.         LocalToGlobal((Point *)&rect.bottom);
  907.         oRect = rect;
  908.         if ( width > 2048 || height > 2048 )
  909.             FitRect(&rect,width,height);
  910.         else if ( width < 1024 && height < 1024 )
  911.             FitRect(&rect,width<<4,height<<4);
  912.         else
  913.             FitRect(&rect,width<<2,height<<2);
  914.         maxH = (rect.right - rect.left);
  915.         maxV = (rect.bottom - rect.top);
  916.         if ( maxV < minV || maxH < minH ) {
  917.             minV = maxV;
  918.             minH = maxH;
  919.         }
  920.         maxV = (maxH * height)/width;
  921.         minV = (minH * height)/width;
  922.     }
  923.     SetRect(&sizeRect,minH,minV,maxH,maxV);
  924.     if ( (size = GrowWindow(wind,*where,&sizeRect))  != 0 ) {
  925.         h = size & 0xffff;
  926.         v = size >> 16;
  927.         if ( maintainAspect )
  928.             v = (h * height)/width;
  929.         DoSizeWindow((CWindowPtr)wind,h,v,true);
  930.     }
  931.     SetPort(savePort);
  932.     FixMenus();
  933. }
  934.  
  935. /************************************************
  936.  *
  937.  *    Handle menu commands.
  938.  *
  939.  ************************************************/
  940.  
  941. void DoCommand(long    mResult)
  942. {
  943.     short         theMenu, theItem;
  944.     GrafPtr    savePort;
  945.     Str255        daName;
  946.  
  947.     theItem = ((mResult) & 0xFFFF);
  948.     theMenu = (((mResult) >> 16) & 0xFFFF);        /* This is the resource ID */
  949.  
  950.     switch (theMenu) {
  951.     case appleMenuID:
  952.         if ( theItem != 1 ) {
  953.             GetMenuItemText(gMenus[0], theItem, daName);
  954.             GetPort(&savePort);
  955.             (void) OpenDeskAcc(daName);
  956.             SetPort(savePort);
  957.         }
  958.         break;
  959.  
  960.     case fileMenuID:
  961.         {
  962.             switch (theItem) {
  963.             case M_OPEN:
  964.                 DoOpen(nil);
  965.                 break;
  966.             case M_CLOSE:
  967.                 DoClose(gActiveWindow);
  968.                 break;
  969.             case M_COMP:
  970.                 DoCompression(gActiveWindow);
  971.                 break;
  972.             case M_SAVE:
  973.                 DoSave(gActiveWindow);
  974.                 break;
  975.             case M_QUIT:
  976.                 gExitFlag = true;            /* Request exit */
  977.                 break;
  978.             }
  979.             FixMenus();
  980.         }
  981.         break;
  982.     case editMenuID:
  983.         if ( !SystemEdit(theItem-1) ) {
  984.             switch ( theItem ) {
  985.             case M_COPY:
  986.                 DoCopy(gActiveWindow);
  987.                 break;
  988.             case M_PASTE:
  989.                 DoPaste();
  990.                 break;
  991.             case M_FIT:
  992.                 DoError();
  993.                 break;
  994.             default:
  995.                 break;
  996.             }
  997.         }
  998.         FixMenus();
  999.         break;
  1000.     default:
  1001.         break;
  1002.     }
  1003.     HiliteMenu(0);
  1004. }
  1005.  
  1006. extern pascal ComponentResult DRAWTEXTCODEC(ComponentParameters *params,Handle storage);
  1007.  
  1008. /************************************************
  1009.  *
  1010.  *    Our program.
  1011.  *
  1012.  ************************************************/
  1013.  
  1014. void main()
  1015. {
  1016.     GrafPtr    savePort;
  1017.     EventRecord myEvent;
  1018.     Rect        dragRect;
  1019.     WindowPtr    whichWindow;
  1020.     long        resp;
  1021.  
  1022.  
  1023.     if ( Initialize() ) {
  1024.         SysBeep(1);
  1025.         ExitToShell();
  1026.     }
  1027.     
  1028.     if ( Gestalt(gestaltSystemVersion, &resp) != noErr || resp < 0x700 ) {
  1029.         gSevenOh = false;
  1030.     } else {
  1031.         gSevenOh = true;
  1032.     }
  1033.     
  1034.     /*    Check to make sure the image compression manager is installed. */
  1035.  
  1036.     if ( Gestalt(gestaltCompressionMgr, &resp) != noErr || resp < 15 ) {
  1037.         SysBeep(1);
  1038.         ExitToShell();
  1039.     }
  1040.  
  1041.     /*    Check to see if new style standard file is around. */
  1042.  
  1043.     gHasNewStdFile = ( Gestalt(gestaltStandardFileAttr,&resp) == 0 );
  1044.  
  1045.     /*    Install and open the standard compression component. */
  1046.  
  1047.     gSCComponent = OpenDefaultComponent('scdi',0);
  1048.     if (!gSCComponent) {
  1049.         SysBeep(1);
  1050.         ExitToShell();
  1051.     }
  1052.     
  1053.     /*    Set up the first defaults for compression dialog. */
  1054.     
  1055.     gSCParams.flags = scListEveryCodec;
  1056.     gSCParams.theCodecType = 'dtxt';
  1057.     gSCParams.theCodec = anyCodec;
  1058.     gSCParams.spatialQuality = codecNormalQuality;
  1059.     gSCParams.temporalQuality = 0;
  1060.     gSCParams.depth = 32;
  1061.  
  1062.  
  1063.  
  1064.     /* install CoDec to test */
  1065.  
  1066.  
  1067.  
  1068.      {
  1069.         ComponentDescription td;
  1070.     
  1071.         Handle    cname = NewHandle(sizeof(CODEC_NAME));
  1072.         Handle    dname = NewHandle(sizeof(CODEC_NAME));
  1073.     
  1074.         td.componentType = 'imco';
  1075.         td.componentSubType = 'dtxt';
  1076.         td.componentManufacturer = 'mark';
  1077.         td.componentFlags = codecInfoDoes1;
  1078.         td.componentFlagsMask = 0;
  1079.         
  1080.         
  1081.         BlockMove(CODEC_NAME,*cname,sizeof(CODEC_NAME));
  1082.         RegisterComponent(&td,NewComponentRoutineProc(DRAWTEXTCODEC), 0,cname,nil, nil);
  1083.             
  1084.         td.componentType = 'imdc';
  1085.         td.componentFlags = codecInfoDoes1;
  1086.         BlockMove(CODEC_NAME,*dname,sizeof(CODEC_NAME));
  1087.         RegisterComponent(&td,NewComponentRoutineProc(DRAWTEXTCODEC), 0,dname,nil, nil);
  1088.     }
  1089.  
  1090.  
  1091.     FixMenus();
  1092.     DoOpen(nil);
  1093.     
  1094.     while (!gExitFlag ) {
  1095.         
  1096.         if ( WaitNextEvent( everyEvent, &myEvent, 1, nil) == 0 )
  1097.             continue;
  1098.         
  1099.         switch (myEvent.what) {
  1100.         case mouseDown:
  1101.             switch ((short)FindWindow(myEvent.where, &whichWindow)) {
  1102.             case inSysWindow:
  1103.                 SystemClick(&myEvent, whichWindow);
  1104.                 FixMenus();
  1105.                 break;
  1106.  
  1107.             case inMenuBar:
  1108.                 DoCommand(MenuSelect(myEvent.where));
  1109.                 break;
  1110.  
  1111.             case inDrag:
  1112.                 GetPort(&savePort);
  1113.                 SetPort((GrafPtr)whichWindow);
  1114.                 SetRect(&dragRect, 4, 20 + 4, qd.screenBits.bounds.right-4, qd.screenBits.bounds.bottom-4);
  1115.                 DragWindow(whichWindow, myEvent.where, &dragRect);
  1116.                 gZoomedPictureFrame = ((CGrafPtr)whichWindow)->portRect;
  1117.                 LocalToGlobal((Point *)&gZoomedPictureFrame.top);
  1118.                 LocalToGlobal((Point *)&gZoomedPictureFrame.bottom);
  1119.                 SetPort(savePort);
  1120.                 break;
  1121.  
  1122.             case inGrow:
  1123.                 DoGrow(whichWindow,&myEvent.where);
  1124.                 break;
  1125.  
  1126.             case inGoAway:
  1127.                 if ( TrackGoAway(whichWindow,myEvent.where)  ) 
  1128.                     DoClose((CWindowPtr)whichWindow);
  1129.                 FixMenus();
  1130.                 break;
  1131.  
  1132.             case inZoomIn:
  1133.                 if ( TrackBox(whichWindow,myEvent.where,inZoomIn)  ) 
  1134.                     DoZoom(whichWindow);
  1135.                 break;
  1136.  
  1137.             case inZoomOut:
  1138.                 if ( TrackBox(whichWindow,myEvent.where,inZoomOut)  ) 
  1139.                     DoZoom(whichWindow);
  1140.                 break;
  1141.  
  1142.             case inContent:
  1143.                 if (whichWindow != FrontWindow()) 
  1144.                     SelectWindow(whichWindow);
  1145.                 break;
  1146.             
  1147.             default:
  1148.                 break;
  1149.             }
  1150.             break;
  1151.  
  1152.         case keyDown:
  1153.             if ( ((myEvent.modifiers & cmdKey) != 0) ) {
  1154.                 char key = myEvent.message & charCodeMask;
  1155.                 DoCommand(MenuKey(key));
  1156.             }
  1157.             break;
  1158.         
  1159.         case updateEvt :
  1160.  
  1161.             DoUpdate((CWindowPtr)myEvent.message);
  1162.             break;
  1163.         
  1164.         case activateEvt:
  1165.                 
  1166.             whichWindow=(WindowPtr)myEvent.message;
  1167.             if ( (myEvent.modifiers & activeFlag) == 0 ) 
  1168.                 gActiveWindow = nil;
  1169.              else 
  1170.                 gActiveWindow = (CWindowPtr)whichWindow;
  1171.             FixMenus();
  1172.             break;
  1173.     
  1174.         default:
  1175.             break;
  1176.             
  1177.         }
  1178.     }
  1179.     DoClose(gActiveWindow);
  1180.     CloseComponent(gSCComponent);
  1181.     ExitToShell();
  1182. }
  1183.